#include "mpp_showing.h"
#include "mpp_display_util.h"
#include <dlfcn.h> 
#include <dlfcn.h> 




mpp_showing::mpp_showing(mpp_screens *screens):
                            m_screens(screens),background_src(NULL),m_rga_ctx(NULL),rga_fd(-1),m_buffer_obj(NULL)
{
    int  ret = 0;
    if(!screens)
        return ;
    this->m_screens->mpp_start_display();
    if(!this->m_rga_ctx)
        this->m_rga_ctx = new rga_context;

    this->m_rga_ctx->rga_handle = NULL;
    this->m_rga_ctx->rga_handle = dlopen("/usr/lib/librga.so", RTLD_LAZY);
    printf("rga_handle %p\n",this->m_rga_ctx->rga_handle);
    if (!m_rga_ctx->rga_handle)
    {
        printf("dlopen /usr/lib/librga.so failed\n");
        return;
    }
    this->m_rga_ctx->init_func = (FUNC_RGA_INIT)dlsym(m_rga_ctx->rga_handle, "c_RkRgaInit");
    if( !this->m_rga_ctx->init_func){
        printf("get c_RkRgaInit error \n");
        return ;
    }
       
    this->m_rga_ctx->deinit_func = (FUNC_RGA_DEINIT)dlsym(m_rga_ctx->rga_handle, "c_RkRgaDeInit");
    if( !this->m_rga_ctx->deinit_func){
        printf("get c_RkRgaDeInit error \n");
        return ;
    }
    this->m_rga_ctx->alloc_buffer = (FUNC_GetAllocBuffer)dlsym(m_rga_ctx->rga_handle, "c_RkRgaGetAllocBuffer");
    if( !this->m_rga_ctx->alloc_buffer){
        printf("get c_RkRgaGetAllocBuffer error \n");
        return ;
    }
    this->m_rga_ctx->get_mmap = (FUNC_GetMmap)dlsym(m_rga_ctx->rga_handle, "c_RkRgaGetMmap");
    if( !this->m_rga_ctx->get_mmap){
        printf("get c_RkRgaGetMmap error \n");
        return ;
    }

    this->m_rga_ctx->get_bufferFd = (FUNC_GetBufferFd)dlsym(m_rga_ctx->rga_handle, "c_RkRgaGetBufferFd");
    if( !this->m_rga_ctx->get_bufferFd){
        printf("get c_RkRgaGetBufferFd error \n");
        return ;
    }
    this->m_rga_ctx->unmap = (FUNC_Unmap)dlsym(m_rga_ctx->rga_handle, "c_RkRgaUnmap");
    if( !this->m_rga_ctx->unmap){
        printf("get unmap error \n");
        return ;
    }
    this->m_rga_ctx->free_buffer = (FUNC_Free)dlsym(m_rga_ctx->rga_handle, "c_RkRgaFree");
    if( !this->m_rga_ctx->free_buffer){
        printf("get c_RkRgaFree error \n");
        return ;
    }

    this->m_rga_ctx->blit_func = (FUNC_RGA_BLIT)dlsym(m_rga_ctx->rga_handle, "c_RkRgaBlit");
    if( !this->m_rga_ctx->blit_func){
        printf("get c_RkRgaBlit error \n");
        return ;
    }
    
    memset(&this->rga_bo,0x00,sizeof(bo_t));
    ret = rga_control_buffer_init(&this->rga_bo,&this->rga_fd, 
                                        this->m_screens->width, this->m_screens->height,
                                        mpp_disp_util::mpp_format_to_bpp(this->m_screens->format) );
    if(ret){
        printf("rga alloc error \n");
        return ;
    }
    // -- 注意这里需要使用的是 文件描述符的FD  this->rga_fd 不是bo的fd   而拷贝数据时要使用的是this->rga_bo.ptr
    printf("RGA BUFFER对象的文件描述符 fd:%d   BUFFER 长度:%d OFFSET:%d PICH:%d  文件描述符 fd:%d \n",
                                    this->rga_bo.fd,this->rga_bo.size,this->rga_bo.offset,this->rga_bo.pitch,this->rga_fd);


}
int mpp_showing::rga_control_buffer_init(bo_t *bo, int *buf_fd, int width, int height, int bpp)
{
        int ret;
        // mpp_disp_util::mpp_format_to_bpp
        ret = this->m_rga_ctx->init_func();
        if (ret) {
            printf("c_RkRgaInit error : %s\n", strerror(errno));
            return ret;
        }
        ret = this->m_rga_ctx->alloc_buffer(bo, width, height, bpp);
        if (ret) {
            printf("c_RkRgaGetAllocBuffer error : %s\n", strerror(errno));
            return ret;
        }

        ret = this->m_rga_ctx->get_mmap(bo);
        if (ret) {
            printf("c_RkRgaGetMmap error : %s\n", strerror(errno));
            return ret;
        }

        ret =  this->m_rga_ctx->get_bufferFd(bo, buf_fd);
        if (ret) {
            printf("c_RkRgaGetBufferFd error : %s\n", strerror(errno));
            return ret;
        }
        return 0;
}
void mpp_showing::rga_control_buffer_deinit(bo_t *bo, int buf_fd)
{
    int ret;

    if (buf_fd >= 0)
        close(buf_fd);
    ret = this->m_rga_ctx->unmap(bo);
    if (ret)
        printf("c_RkRgaUnmap error : %s\n", strerror(errno));
    ret =  this->m_rga_ctx->free_buffer (bo);
    if (ret)
        printf("c_RkRgaFree error : %s\n", strerror(errno));
}
bool mpp_showing::is_showing()
{
    if(this->m_screens)
        return m_screens->mpp_is_startDisplay();
    return false;
}
mpp_showing::~mpp_showing()
{
    if(this->background_src)
        delete this->background_src;
    if(this->m_rga_ctx){

        this->m_rga_ctx->deinit_func();
        dlclose( this->m_rga_ctx->rga_handle);
        delete this->m_rga_ctx;
        this->m_rga_ctx = NULL;
    }
    if(this->rga_fd>0){
        rga_control_buffer_deinit(&this->rga_bo,this->rga_fd);
        this->rga_fd = -1;
    }
    
    if(this->m_buffer_obj){
        if (this->m_buffer_obj->fb_id) {
                //printf("free bo's id.\n");
            int ret = drmModeRmFB(m_screens->mpp_display_dev_get_fd(), this->m_buffer_obj->fb_id);
            if (ret)
                printf("failed to exec drmModeRmFB.\n");
        }
        if (this->m_buffer_obj->t_handle) {
            struct drm_gem_close req = {
                    .handle = this->m_buffer_obj->t_handle,
            };
            //printf("free bo's handle.\n");
            drmIoctl(m_screens->mpp_display_dev_get_fd(), DRM_IOCTL_GEM_CLOSE, &req);
        }
        free(this->m_buffer_obj);
        this->m_buffer_obj = NULL;
    }
        
        
}

void mpp_showing::mpp_drow_background(string path)
{
    FILE *file_path = NULL;
    uint32_t src_length = 0;
    
        if(this->m_screens && this->m_screens->format == DRM_FORMAT_XRGB8888){
            if(!this->background_src){
                // file_path = fopen(path.c_str(),"r");
                // if(file_path){
                //     this->background_src = new uint8_t[this->m_screens->width*4];
                //     if( this->background_src != NULL){
                //             memset(this->background_src,0x00,this->m_screens->width*4);
                //             for(int i = 0;i<this->m_screens->height;i++){
                //             src_length = fread(this->background_src,1,this->m_screens->width*4,file_path);
                                
                            
                //                 uint8_t *rgax=  (uint8_t*)this->m_screens->m_current_screens->buffer->mpp_buffer_get_addr()+
                //                                                     i*this->m_screens->width*4;
                //                 for(int x=0;x<m_screens->width ;x++){
                //                             rgax[ x*4+0] = this->background_src[x*4+3]; //x
                //                             rgax[ x*4+1] = this->background_src[x*4+0]; //r
                //                             rgax[ x*4+2] = this->background_src[x*4+1]; //g
                //                             rgax[ x*4+3] = this->background_src[x*4+2]; //b
                //                 }
                //             }
                //     }
                //     fclose(file_path);
                // }

                file_path = fopen(path.c_str(),"r");
                if(file_path){
                    this->background_src = new uint8_t[this->m_screens->width*4];
                    if( this->background_src != NULL){
                            memset(this->background_src,0x00,this->m_screens->width*4);
                            uint8_t *tmpaddr = (uint8_t *)this->rga_bo.ptr;
                            for(int i = 0;i<this->m_screens->height;i++){
                                src_length = fread(&tmpaddr[(i * this->m_screens->width*4)],1,this->m_screens->width*4,file_path);


                                // uint8_t *rgax=  (uint8_t*)this->m_screens->m_current_screens->buffer->mpp_buffer_get_addr()+
                                //                 i*this->m_screens->width*4;
                                // for(int x=0;x<m_screens->width ;x++){
                                //             rgax[ x*4+0] = tmpaddr[(i * this->m_screens->width*4)+x*4+3]; //x
                                //             rgax[ x*4+1] = tmpaddr[(i * this->m_screens->width*4)+x*4+0]; //r
                                //             rgax[ x*4+2] = tmpaddr[(i * this->m_screens->width*4)+x*4+1]; //g
                                //             rgax[ x*4+3] = tmpaddr[(i * this->m_screens->width*4)+x*4+2]; //b
                                //}

 
                             }
                     }
                    mpp_disp_util::depict_shape depict ;

                    this->m_buffer_obj = (buffer_obj *)calloc(1, sizeof(buffer_obj));

                    memset(this->m_buffer_obj,0x00,sizeof(buffer_obj));

                    drmPrimeFDToHandle(m_screens->mpp_display_dev_get_fd(),  this->rga_fd, &m_buffer_obj->t_handle);       //首先把RGA的FD传到DRM中

                    memset(&depict,0x00,sizeof(mpp_disp_util::depict_shape));
                    mpp_disp_util::mpp_format_depict_sharp(m_screens->format,m_screens->width,
                                                                                        m_screens->height,m_buffer_obj->t_handle,
                                                                                        m_screens->m_current_screens->buffer->pitch,&depict);         // --然后通过本人写的工具类得到depict 值(此类的头文件已经有详细的介绍)

                    drmModeAddFB2(m_screens->mpp_display_dev_get_fd(), m_screens->width, m_screens->height,
                                                                        m_screens->format, depict.handles, depict.pitches, depict.offsets,
                                                                        &m_buffer_obj->fb_id, 0);  //--最后把这些值都加入DRM的BUF中，得到    m_buffer_obj->fb_id
                        
                    }   
                     fclose(file_path);
                }
                
        }else{

        }
}



int mpp_showing::mpp_show_background(string path)
{

    //--需要将背景显示的BUFFER的ID给到drmModeSetPlane就可以显示了
    int ret = 0;
    mpp_drow_background(path);
    if(this->m_screens  ){
        
        if(m_buffer_obj && m_buffer_obj->fb_id > 0){
            ret = m_screens->mpp_setPlane(m_buffer_obj->fb_id,//m_screens->m_current_screens->buffer->mpp_buffer_get_id(),   //--将BUFFER ID赋值就可以显示
                                                                0, 0, 0,
                                                                m_screens->m_current_screens->crtc->mode.hdisplay,
                                                                m_screens->m_current_screens->crtc->mode.vdisplay,
                                                                0, 0,  m_screens->width << 16,  m_screens->height << 16);
            if (ret){
                printf("failed to exec mpp_setPlane.\n");       
                return ret;
            }
        }
            
           
        
        //  if(this->m_buffer_obj){
        //      if (this->m_buffer_obj->fb_id) {
        //              //printf("free bo's id.\n");
        //             ret = drmModeRmFB(m_screens->mpp_display_dev_get_fd(), this->m_buffer_obj->fb_id);
        //             if (ret)
        //                 printf("failed to exec drmModeRmFB.\n");
        //         }
        //         if (this->m_buffer_obj->t_handle) {
        //             struct drm_gem_close req = {
        //                     .handle = this->m_buffer_obj->t_handle,
        //             };
        //             //printf("free bo's handle.\n");
        //             drmIoctl(m_screens->mpp_display_dev_get_fd(), DRM_IOCTL_GEM_CLOSE, &req);
        //         }
        //         free(this->m_buffer_obj);
        //         this->m_buffer_obj = NULL;
        //  }
         
        
        // if(this->m_buffer_obj){
        //     this->m_buffer_obj->fb_id = fb_id;
        //     this->m_buffer_obj->t_handle = t_handle;
        // }
    }
    return ret;
}
int mpp_showing::mpp_show_yuv(int fd,uint32_t width,uint32_t height,void *date)
{
    return 0;
}
int mpp_showing::mpp_show_rgba(int fd,uint32_t width,uint32_t height,void *date)
{
    return 0;
}

